﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG

using FRL.DebtChased.Extensions;
using FRL.DebtChased.Repository;
using FRL.DebtChased.Silverlight.Library;
using FRL.DebtChased.Silverlight.Library.RichContentService;
using FRL.DebtChased.ClientEditor;

using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Data;


namespace FRL.DebtChased.Views
{
    public partial class ClientEditorCtrl : UserControl
    {

        /////////////////////////////////////////////////////////////
		// Constants

		private const string DefaultSearchText = "[client name/city]";

		private const string ClientTitle = "Client Details";

		/////////////////////////////////////////////////////////////
		// Attributes

		private int m_iCurrentClientId = 0;


		/////////////////////////////////////////////////////////////
		// Construction

        public ClientEditorCtrl()
        {
            InitializeComponent();

            // Set colours and inital text
            // txtSearch.Text = DefaultSearchText;

        }

        public void OnMainLoadFinished()
        {
            // Do the initial load of data
           // _initialDataLoad();

            // Setup controls
            //_setupControls();
            tabContacts.Contacts = new ObservableCollection<ContactTransport>();
        }

		/////////////////////////////////////////////////////////////
		#region Event Handlers

		protected void butNew_Click(object sender, EventArgs e)
		{

			// Confirmation
			if (!MessageBoxes.PopupOption("Discard current client details?"))
				return;

			// Set a new client
			//_setNewClient();

			// Setup controls
			//_setupControls();

		}

		protected void butSave_Click(object sender, EventArgs e)
		{
            /*
			// Get the client details
			ClientTransport client = _getClient();
			if (client == null)
				return;

			// Confirmation
			if (!MessageBoxes.PopupOption("Save changes to client?"))
				return;

			// Development message
//#if !DEBUG
			MessageBoxes.PopupDevMessage();
			return;
//#endif // #if !DEBUG

			// Save the client
			//_saveClient(client);
            /**/
		}

		protected void butRevert_Click(object sender, EventArgs e)
		{
			// Reload the client
			//_loadClient(m_iCurrentClientId);
		}

		protected void butSearch_Click(object sender, EventArgs e)
		{

			// Check the search text
			if (
				(txtSearch.Text.Length < 2)
				||
				(txtSearch.Text == DefaultSearchText)
			)
			{

				// Message for user and exit
				MessageBoxes.PopupMessage("The search must be at least 2 characters.");
				return;

			}

			// Call search function
			//_startSearch(txtSearch.Text);

		}

		private void clientDetailsCtrl_ClientNameChanged(object sender, EventArgs e)
		{

			// Update client title
			//_updateClientTitle();

		}

		#endregion Event Handlers

        private void HeadingBarCtrl_ExpandChange(object sender, EventArgs e)
        {

        }

        private void ClientSettingsHeader_ExpandChange(object sender, EventArgs e)
        {
            ClientSettingsHeader.IsArrowUp = !ClientSettingsHeader.IsArrowUp;
            ClientSettingsBody.Visibility = ClientSettingsHeader.IsArrowUp ? Visibility.Visible : Visibility.Collapsed;
        }

        private void TextBox_ContentChanged(object sender, TextChangedEventArgs e)
        {

        }

        private GridLength _gridLengthAuto = new GridLength(1, GridUnitType.Auto);
        private GridLength _gridLengthStar = new GridLength(1, GridUnitType.Star);
        private void CommentsCtrl_ExpandChange(object sender, PanelExpandChangeEventArgs e)
        {
            CommentsRow.Height = e.IsExpanded ? _gridLengthStar : _gridLengthAuto;
        }

		/////////////////////////////////////////////////////////////
		//#region Operations

        /*
		private ClientTransport _getClient()
		{

			// Populate the client object with details from the control
			// and display errors in the user input

			// Declare return variable
			ClientTransport Ftmp = new ClientTransport();
			Ftmp.ClientId = m_iCurrentClientId;
			Ftmp.ClientInstructionBatchList = new System.Collections.ObjectModel.ObservableCollection<ClientInstructionBatchTransport>();
			Ftmp.Contacts = new System.Collections.ObjectModel.ObservableCollection<ContactTransport>();
			Ftmp.BankAccounts = new System.Collections.ObjectModel.ObservableCollection<BankAccountTransport>();

			// Declaration of local variables
			List<string> Errors = new List<string>();

			// Get the client details
			clientDetailsCtrl.Get(Ftmp, Errors);
			managerCtrl.Get(Ftmp, Errors);
			bankAccountTabCtrl.Get(Ftmp, Errors);
			clientInstructionBatchCtrl.Get(Ftmp, Errors);

			// Get the contacts
			List<ContactTransport> contacts = tabContacts.Get(Errors);
			foreach (ContactTransport contact in contacts)
				Ftmp.Contacts.Add(contact);
			if (contacts.Count == 0)
				Errors.Add("A client must have at least one contact.");

			// If there are errors...
			if (Errors.Count > 0)
			{
				MessageBoxes.PopupErrors(Errors);
				Ftmp = null;
			}

			// Return variable
			return Ftmp;

		}

		private void _setupControls()
		{

			// Enable/disable buttons
			butRevert.IsEnabled = (m_iCurrentClientId != 0);

			// Show/hide search controls
			bool bClientUser = (
				(CachedData.Singleton.UserSessionTransport != null)
				&&
				((CachedData.Singleton.UserSessionTransport.Roles & (int)(Definitions.eRoles.CLIENT_ADMIN|Definitions.eRoles.CLIENT_USER)) != 0)
			);
			searchStack.Visibility = bClientUser ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
			butNew.Visibility = bClientUser ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;

		}

        
		private void _setClientTransport(ClientTransport clientTransport)
		{

			// Retain the client id
			m_iCurrentClientId = clientTransport.ClientId;

			// Set controls
			clientDetailsCtrl.Set(clientTransport);
            tabContacts.Contacts = clientTransport.Contacts;
			managerCtrl.Set(clientTransport);
			clientInstructionBatchCtrl.Set(clientTransport);
			bankAccountTabCtrl.Set(clientTransport,false);

			// Update client title
			_updateClientTitle();

		}

		private void _setNewClient()
		{

			// Reset id
			m_iCurrentClientId = 0;

			// Set controls from an empty client
			ClientTransport clientTransport = new ClientTransport();
			clientTransport.ClientInstructionBatchList = new System.Collections.ObjectModel.ObservableCollection<ClientInstructionBatchTransport>();
			clientTransport.Contacts = new System.Collections.ObjectModel.ObservableCollection<ContactTransport>();
			clientTransport.BankAccounts = new System.Collections.ObjectModel.ObservableCollection<BankAccountTransport>();
			_setClientTransport(clientTransport);

		}

		private void _updateClientTitle()
		{

			// Compose title
			if (clientDetailsCtrl.txtClientName.Text.Length > 0)
				tbClientTitle.Text = string.Format("{0} - {1}", ClientTitle, clientDetailsCtrl.txtClientName.Text);
			else
				tbClientTitle.Text = string.Format("{0} - [new client]", ClientTitle);

		}

		#endregion Operations

		/////////////////////////////////////////////////////////////
		#region Animations

		private void barBankAndInvoice_Expanded(object sender, EventArgs e)
		{

			// Animation for raising and lowering bank account tab

			// TODO 
			// Now that this design has been approved, convert to xaml to reduce code volume

			// Create easing function
			EasingFunctionBase func = new CircleEase();
			func.EasingMode = EasingMode.EaseInOut;

			// Create animations for the tab control
			DoubleAnimation animTabCtrl = new DoubleAnimation();
			animTabCtrl.Duration = new Duration(new TimeSpan(50 * 1000 * 100));
			animTabCtrl.EasingFunction = func;

			// Add events
			animTabCtrl.Completed += new EventHandler(LeftTabStoryBoard_Completed);
			animTabCtrl.From = bankAccountTabCtrl.ActualHeight;

			// If expanding bank details...
			if (bankAccountTabCtrl.Height < bankAccountTabCtrl.MaxHeight)
			{
				bankAccountTabCtrl.Visibility = System.Windows.Visibility.Visible;
				animTabCtrl.To = bankAccountTabCtrl.MaxHeight;
				barBankAndInvoice.IsArrowUp = false;
			}
			else
			{
				bankAccountTabCtrl.Height = 0;
				barBankAndInvoice.IsArrowUp = true;
			}

			// Setup the story board
			Storyboard storyboard = new Storyboard();
			storyboard.Children.Add(animTabCtrl);
			Storyboard.SetTarget(animTabCtrl, bankAccountTabCtrl);
			Storyboard.SetTargetProperty(animTabCtrl, new PropertyPath("(Height)"));

			// Begin the storyboard
			storyboard.Begin();

		}

		void LeftTabStoryBoard_Completed(object sender, EventArgs e)
		{

			// If expanded manager details...
			if (bankAccountTabCtrl.Height == bankAccountTabCtrl.MaxHeight)
			{

			}
			else
			{

				// When the tab control is reduced to zero-height, hide it

				// Hide the tab control
				bankAccountTabCtrl.Visibility = System.Windows.Visibility.Collapsed;

			}

		}

		private void barClientManagers_Expanded(object sender, EventArgs e)
		{

			// Animation for raising and lowering client managers panel

			// TODO 
			// Now that this design has been approved, convert to xaml to reduce code volume

			// Create easing function
			EasingFunctionBase func = new CircleEase();
			func.EasingMode = EasingMode.EaseInOut;

			// Create animations for the tab control
			DoubleAnimation animTabCtrl = new DoubleAnimation();
			animTabCtrl.Duration = new Duration(new TimeSpan(50 * 1000 * 100));
			animTabCtrl.EasingFunction = func;

			// Add events
			animTabCtrl.Completed += new EventHandler(RightTabStoryBoard_Completed);
			animTabCtrl.From = scrollManagers.ActualHeight;

			// If expanding manager details...
			if (scrollManagers.Height < scrollManagers.MaxHeight)
			{
				animTabCtrl.To = scrollManagers.MaxHeight;
				scrollManagers.Visibility = System.Windows.Visibility.Visible;
				barClientManagers.IsArrowUp = false;
			}
			else
			{
				animTabCtrl.To = scrollManagers.MinHeight;
				barClientManagers.IsArrowUp = true;
			}

			// Setup the story board
			Storyboard storyboard = new Storyboard();
			storyboard.Children.Add(animTabCtrl);
			Storyboard.SetTarget(animTabCtrl, scrollManagers);
			Storyboard.SetTargetProperty(animTabCtrl, new PropertyPath("(Height)"));

			// Begin the storyboard
			storyboard.Begin();

		}

		void RightTabStoryBoard_Completed(object sender, EventArgs e)
		{

			// If contracted...
			if (scrollManagers.Height < scrollManagers.MaxHeight)
			{

			}
			else
			{

			}

		}

		private void txtSearch_GotFocus(object sender, RoutedEventArgs e)
		{

			// If the text is the initial text...
			if (txtSearch.Text == DefaultSearchText)
			{
				txtSearch.Text = "";
				txtSearch.Foreground = new SolidColorBrush(Colors.Black);
			}

		}

		#endregion Animations

		/////////////////////////////////////////////////////////////
		#region Rich content service operations

		private void _loadClient(int iClientId)
		{

			// Show hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(true);

			try
			{

				// Load the client
#if USEFAKEDATA

				// Create event
				object[] results = new object[1];
				results[0] = CachedData.GetDummyClientTransport();
				GetClientCompletedEventArgs e = new GetClientCompletedEventArgs(
					results,
					null,
					false,
					null
				);

				// Process fake client data
				proxy_GetClientCompleted(null, e);

//#else

				// Download the client
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.GetClientCompleted += new EventHandler<GetClientCompletedEventArgs>(proxy_GetClientCompleted);
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.GetClientAsync(iClientId);

//#endif // #if USEFAKEDATA

			}
			catch (Exception x)
			{

				// Message for user
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to load client.\n\n{0}", x.ToDetailsString()));

			}

		}

		private void _initialDataLoad()
		{

			// If the supporting data is not loaded...
			if (CachedData.Singleton.CountryMap == null)
			{

				// Show hourglass
				MainPage.Singleton.hourglassCtrl.IncShowCount(true);

				// Load real or fake supporting data
//#if USEFAKEDATA

				// Create event
				object[] results = new object[1];
				results[0] = CachedData.GetDummySupportingData();
				GetClientEditorSupportDataCompletedEventArgs e = new GetClientEditorSupportDataCompletedEventArgs(
					results,
					null,
					false,
					null
				);

				// Call completed event
				proxy_GetClientEditorSupportDataCompleted(null, e);

//#else

				// Start by downloading the supporting data
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.GetClientEditorSupportDataCompleted += new EventHandler<GetClientEditorSupportDataCompletedEventArgs>(proxy_GetClientEditorSupportDataCompleted);
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.GetClientEditorSupportDataAsync();

//#endif // #if USEFAKEDATA

			}
			else
			{

				// If there is an client to load...
				if (CachedData.Singleton.UserSessionTransport.ClientId != 0)
				{

					// Load the client
					_loadClient(CachedData.Singleton.UserSessionTransport.ClientId);

				}
				else
				{

					// Create an empty client to edit
					_setNewClient();

					// Setup controls
					_setupControls();

				}

			}

		}

		void proxy_GetClientCompleted(object sender, GetClientCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result == null)
				MessageBoxes.PopupMessage_InternalError("Failed to load client from server.");
			else
			{

				// Update the controls
				_setClientTransport(e.Result);

			}

			// Setup controls
			_setupControls();

		}

		void proxy_GetClientEditorSupportDataCompleted(object sender, GetClientEditorSupportDataCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result == null)
				MessageBoxes.PopupMessage_InternalError("Failed to load supporting data from server.");
			else
			{

				// Update the cached data
				CachedData.Singleton.AddIncoming(e.Result);

				// Update the controls
				bankAccountTabCtrl.PostSupportDataLoaded();
				clientDetailsCtrl.PostSupportDataLoaded();
				managerCtrl.PostSupportDataLoaded();

				// Call loading function again
				_initialDataLoad();

			}

			// Setup controls
			_setupControls();

		}

		private void _saveClient(ClientTransport client)
		{

			// Show hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(true);

			try
			{

				// Initialize a save function
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.SetClientCompleted += new EventHandler<SetClientCompletedEventArgs>(proxy_SetClientCompleted);
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.SetClientAsync(client);

			}
			catch (Exception x)
			{

				// Message for user
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to save client.\n\n{0}", x.ToDetailsString()));

			}

		}

		void proxy_SetClientCompleted(object sender, SetClientCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result != null)
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to save client.  {0}", e.Result));
			else
			{
//#if DEBUG
				Debug.Assert(
					(e.clientTransport.ClientId != 0)
					&&
					(
						(m_iCurrentClientId == 0)
						||
						(m_iCurrentClientId == e.clientTransport.ClientId)
					)
				);
//#endif // #if DEBUG

				// Update the id
				m_iCurrentClientId = e.clientTransport.ClientId;

				// Inform the controls of the new contact ids
				clientDetailsCtrl.Set(e.clientTransport);
                tabContacts.Contacts = e.clientTransport.Contacts;
				clientInstructionBatchCtrl.Set(e.clientTransport);
				managerCtrl.Set(e.clientTransport);
				clientInstructionBatchCtrl.Set(e.clientTransport);
				bankAccountTabCtrl.Set(e.clientTransport, true);

			}

			// Setup controls
			_setupControls();

		}

		private void _startSearch(string strSearch)
		{

			// Show hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(true);

			try
			{

				// Initialize a save function
				RichContentServiceClient proxy = new RichContentServiceClient();
				proxy.SearchClientsCompleted += new EventHandler<SearchClientsCompletedEventArgs>(proxy_SearchClientsCompleted);
				proxy.Endpoint.Address = ExtensionsForSilverlight.CreateDebtChasedEndpoint();
				proxy.SearchClientsAsync(strSearch);

			}
			catch (Exception x)
			{

				// Message for user
				MessageBoxes.PopupMessage_InternalError(string.Format("Failed to search clients.\n\n{0}", x.ToDetailsString()));

			}

		}

		void proxy_SearchClientsCompleted(object sender, SearchClientsCompletedEventArgs e)
		{

			// Hide hourglass
			MainPage.Singleton.hourglassCtrl.IncShowCount(false);

			// Get the result
			if (e.Error != null)
				MessageBoxes.PopupMessage(e.Error.Message);
			else if (e.Result == null)
				MessageBoxes.PopupMessage(Definitions.InternalError);
			else
			{

				// If there are some results
				if (e.Result.Count > 0)
				{
					ClientSearchResultsWnd wndResults = new ClientSearchResultsWnd(e.Result.ToList());
					wndResults.Closed += new EventHandler(wndResults_Closed);
					wndResults.Show();
				}
				else
					MessageBoxes.PopupMessage_InternalError("Search returned no results.");

			}

			// Setup controls
			_setupControls();

		}

		void wndResults_Closed(object sender, EventArgs e)
		{

			// Get the selected id
			ClientSearchResultsWnd wnd = sender as ClientSearchResultsWnd;
			if (wnd.DialogResult == true)
				_loadClient(wnd.SelectedClientId);

		}

		//#endregion Rich content service operations

        private void OldClientStatsExpandClick(object sender, EventArgs e)
        {
            OldClientStats.IsUpsideDown = !OldClientStats.IsUpsideDown;
            tabStatsAndInfo.Visibility = OldClientStats.IsUpsideDown ? Visibility.Collapsed : Visibility.Visible;
        }

        /**/

    }



}
